﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ServiceTester {
    using System.Diagnostics;
    using System.IO;

    using ServiceTester.ServerRentIt11;

    public partial class frmMovieInfo : Form {
        public int movieId = -1;

        private MovieEntry entry;

        private UserSession uSession;
        private RentItClient rClient;

        private Dictionary<string, GenreEntry> availGenres = new Dictionary<string, GenreEntry>();
        private HashSet<string> addedGenres = new HashSet<string>(); 

        private string allowedThumbExt;

        private string allowedMovieExt;

        public frmMovieInfo(frmAdmin fromAdmin, int movieId) {
            if (fromAdmin != null) {
                InitializeComponent();
                uSession = fromAdmin.uSession;
                rClient = fromAdmin.rClient;
                this.movieId = movieId;
            } else {
                throw new ArgumentException("A Admin Client Form must be specified!");
            }
        }

        private void frmMovieInfo_Load(object sender, EventArgs e) {
            this.GetGenres();
            this.GetParentalGuidance();
            this.GetInfo();
        }

        private void GetInfo() {
            btnDownloadHD.Enabled = false;
            entry = rClient.MovieInfo(movieId);
            this.Text = "Movie Info: " + entry.Title;
            txtId.Text = entry.Id.ToString();
            txtTitle.Text = entry.Title;
            numYear.Value = (entry.Year >= numYear.Minimum ? (entry.Year <= numYear.Maximum ? entry.Year : numYear.Maximum) : numYear.Minimum);
            numLength.Value = (entry.Length >= numLength.Minimum ? (entry.Length <= numLength.Maximum ? entry.Length : numLength.Maximum) : numLength.Minimum);
            txtLanguage.Text = entry.Language;
            cmbParentalGuidance.Text = entry.ParentalGuidance.ToString();
            rdbHDYes.Checked = entry.HighDefinition == XBool.True;
            rdbHDNo.Checked = entry.HighDefinition == XBool.False;
            txtRelease.Text = entry.ReleaseDate.HasValue ? entry.ReleaseDate.Value.ToString("yyyy-MM-dd") : "Unreleased";
            txtSummary.Text = entry.Summary;
            txtImdbId.Text = entry.ImdbId;

            addedGenres.Clear();
            lstGenre.Items.Clear();
            foreach (var genre in entry.Genre) {
                lstGenre.Items.Add(genre.Name);
                addedGenres.Add(genre.Name);
            }

            picThumb.ImageLocation = "";
            picThumb.ImageLocation = entry.ThumbUrl;
            btnDownloadHD.Enabled = rdbHDYes.Checked;
        }

        private void GetGenres() {
            var genres = rClient.ListGenres();
            cmbAvailableGenres.Items.Clear();

            foreach (var genre in genres) {
                availGenres[genre.Name] = genre;
                cmbAvailableGenres.Items.Add(genre.Name);
            }

            if (cmbAvailableGenres.Items.Count > 0) cmbAvailableGenres.SelectedIndex = 0;
        }

        private void GetParentalGuidance() {
            cmbParentalGuidance.Items.Clear();

            foreach(var enumVal in Enum.GetNames(typeof(ParentalGuidance))) {
                if(enumVal != "Ignore") cmbParentalGuidance.Items.Add(enumVal);
            }

            if(cmbParentalGuidance.Items.Count > 0) cmbParentalGuidance.SelectedIndex = 0;
        }

        private void btnClose_Click(object sender, EventArgs e) {
            this.Close();
        }

        private void btnRefresh_Click(object sender, EventArgs e) {
            btnRefresh.Enabled = false;
            this.GetInfo();
            btnRefresh.Enabled = true;
            btnRefresh.Focus();
        }

        private void btnSave_Click(object sender, EventArgs e) {
            btnSave.Enabled = false;

            if (uSession != null && uSession.UserId > 0 && uSession.IsAdmin) {
                var mEntry = new MovieEntry
                    {
                        Title = this.txtTitle.Text,
                        Year = (int)this.numYear.Value,
                        Length = (int)this.numLength.Value,
                        Language = this.txtLanguage.Text,
                        ParentalGuidance = rClient.GetParentalGuidance(this.cmbParentalGuidance.Text),
                        HighDefinition = (this.rdbHDYes.Checked ? XBool.True : XBool.False),
                        ImdbId = txtImdbId.Text
                    };

                var rday = DateTime.MinValue;
                DateTime.TryParse(txtRelease.Text, out rday);
                mEntry.ReleaseDate = rday;

                mEntry.Summary = txtSummary.Text;

                var res = rClient.EditMovie(uSession, movieId, mEntry);

                if(res) {
                    res &= this.SaveGenres();
                }

                MessageBox.Show(
                    res ? "Movie edited successfully!" : "Failed to edit movie!",
                    "Save Result",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);

                if (res) btnRefresh.PerformClick();
            } else {
                MessageBox.Show(
                    "You have to be logged in to an admin account if you wish to edit movies!",
                    "Admin Login Required",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }

            btnSave.Enabled = true;
            btnSave.Focus();
        }

        private bool SaveGenres() {
            var toAdd = (from object genre in this.lstGenre.Items
                         where !this.addedGenres.Contains(genre.ToString())
                         select this.availGenres[genre.ToString()]).ToList();
            var toDelete = (from string genre in addedGenres 
                            where !lstGenre.Items.Contains(genre) 
                            select this.availGenres[genre]);

            var res = toAdd.Aggregate(true, (current, genre) => current & this.rClient.AddMovieGenre(uSession, this.movieId, genre.Id));
            res = toDelete.Aggregate(res, (current, genre) => current & this.rClient.RemoveMovieGenre(uSession, this.movieId, genre.Id));

            return res;
        }

        private void btnAddGenre_Click(object sender, EventArgs e) {
                var genreId = availGenres.ContainsKey(cmbAvailableGenres.Text)
                                  ? availGenres[cmbAvailableGenres.Text].Id
                                  : -1;

                if (genreId > -1) {
                    lstGenre.Items.Add(cmbAvailableGenres.Text);
                }
        }

        private void btnRemoveSelectedGenre_Click(object sender, EventArgs e) {
            if (lstGenre.SelectedItems.Count > 0) {
                for (var i = lstGenre.SelectedIndices.Count - 1; i >= 0; i--) {
                    lstGenre.Items.RemoveAt(lstGenre.SelectedIndices[i]);
                }
            }
        }

        private void GetThumbFileExt() {
            var exts = rClient.AllowedThumbFileExtensions();
            // Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|
            if (exts.Length < 1) return;
            var strExts = new string[exts.Length + 1];
            for(var i = 0; i < exts.Length; i++) {
                strExts[i] = "*" + exts[i];
            }
            allowedThumbExt = "Image Files (" + string.Join(";", strExts) + ")|" + string.Join(";", strExts);
        }

        private void GetMovieFileExt() {
            var exts = rClient.AllowedMovieFileExtensions();
            if (exts.Length < 1) return;
            var strExts = new string[exts.Length + 1];
            for (var i = 0; i < exts.Length; i++) {
                strExts[i] = "*" + exts[i];
            }
            allowedMovieExt = "Movie Files (" + string.Join(";", strExts) + ")|" + string.Join(";", strExts);
        }

        private void btnThumbFindFile_Click(object sender, EventArgs e) {
            if(string.IsNullOrEmpty(allowedThumbExt)) this.GetThumbFileExt();
            OFD.Filter = allowedThumbExt;
            if(OFD.ShowDialog() == DialogResult.OK) {
                txtThumbFile.Text = OFD.FileName;
            }
        }

        private void btnUploadThumb_Click(object sender, EventArgs e) {
            btnUploadThumb.Enabled = false;

            if (uSession != null && uSession.UserId > 0 && uSession.IsAdmin) {
                if (File.Exists(txtThumbFile.Text)) {
                    var fi = new FileInfo(txtThumbFile.Text);
                    var uInfo = new UploadFileInfo();
                    var res = false;
                    uInfo.Admin = uSession;
                    uInfo.MovieId = movieId;
                    uInfo.Filename = fi.Name;
                    uInfo.Size = fi.Length;
                    using( var fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        uInfo.FileByteStream = fs;
                        res = rClient.UploadMovieThumb(uInfo.Admin, uInfo.Filename, false, uInfo.MovieId, uInfo.Size, uInfo.FileByteStream);
                    }

                    if(res) {
                        lblThumbResult.Text = "File uploaded!";
                        btnRefresh.PerformClick();
                    }else {
                        lblThumbResult.Text = "Failure!";
                    }
                } else {
                    lblThumbResult.Text = "Invalid file!";
                }
            } else {
                MessageBox.Show(
                    "You have to be logged in to an admin account if you wish to edit movies!",
                    "Admin Login Required",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }

            btnUploadThumb.Enabled = true;
        }

        private void btnDownload_Click(object sender, EventArgs e) {
            var p = Process.Start(entry.MovieDownloadUrl);
        }

        private void btnDownloadHD_Click(object sender, EventArgs e) {
            var p = Process.Start(entry.MovieDownloadUrlHD);
        }

        private void btnIMDBUpdate_Click(object sender, EventArgs e) {
            btnIMDBUpdate.Enabled = false;

            if (!string.IsNullOrEmpty(entry.ImdbId)) {
                var imdb = rClient.GetImdbMovie(entry.ImdbId);
                txtTitle.Text = imdb.Title;
                numYear.Value = (imdb.Year >= numYear.Minimum ? (imdb.Year <= numYear.Maximum ? imdb.Year : numYear.Maximum) : numYear.Minimum);
                numLength.Value = (imdb.Length >= numLength.Minimum ? (imdb.Length <= numLength.Maximum ? imdb.Length : numLength.Maximum) : numLength.Minimum);
                txtLanguage.Text = imdb.Language;
                cmbParentalGuidance.Text = imdb.ParentalGuidance.ToString();
                txtRelease.Text = imdb.ReleaseDate.ToString("yyyy-MM-dd");
                txtSummary.Text = imdb.Summary;

                lstGenre.Items.Clear();
                foreach (var genre in imdb.Genre) {
                    lstGenre.Items.Add(genre.Name);
                }

                if (imdb.ThumbData != null) {
                    picThumb.Image.Dispose();
                    var fi = new FileInfo(Application.ExecutablePath);
                    var thumbFilename = fi.DirectoryName + "\\thumb_" + entry.ImdbId + ".jpg";
                    
                    var fs = new FileStream(thumbFilename, FileMode.Create, FileAccess.Write, FileShare.Write);
                    fs.Write(imdb.ThumbData, 0, imdb.ThumbData.Length);
                    fs.Close();

                    /*picThumb.Image = Image.FromFile(thumbFilename);*/
                    using (MemoryStream ms = new MemoryStream(imdb.ThumbData)) {
                        using (Image img = Image.FromStream(ms)) {
                            picThumb.Image = (Image)img.Clone();
                        }
                    }

                    txtThumbFile.Text = thumbFilename;
                }
            }

            btnIMDBUpdate.Enabled = true;
        }

        private void btnFindMovieFile_Click(object sender, EventArgs e) {
            if (string.IsNullOrEmpty(allowedMovieExt)) this.GetMovieFileExt();
            OFD.Filter = allowedMovieExt;
            if (OFD.ShowDialog() == DialogResult.OK) {
                txtMovieFile.Text = OFD.FileName;
            }
        }

        private void btnMovieUpload_Click(object sender, EventArgs e) {
            btnMovieUpload.Enabled = false;

            if (uSession != null && uSession.UserId > 0 && uSession.IsAdmin) {
                if (File.Exists(txtMovieFile.Text)) {
                    var fi = new FileInfo(txtMovieFile.Text);
                    var uInfo = new UploadFileInfo();
                    var res = false;
                    uInfo.Admin = uSession;
                    uInfo.MovieId = movieId;
                    uInfo.Filename = fi.Name;
                    uInfo.Size = fi.Length;
                    using (var fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        uInfo.FileByteStream = fs;
                        res = rClient.UploadMovieFile(uInfo.Admin, uInfo.Filename, chkUploadHD.Checked, uInfo.MovieId, uInfo.Size, uInfo.FileByteStream);
                    }

                    if (res) {
                        lblMovieUploadResult.Text = "File uploaded!";
                        btnRefresh.PerformClick();
                    } else {
                        lblMovieUploadResult.Text = "Failure!";
                    }
                } else {
                    lblMovieUploadResult.Text = "Invalid file!";
                }
            } else {
                MessageBox.Show(
                    "You have to be logged in to an admin account if you wish to edit movies!",
                    "Admin Login Required",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }

            btnMovieUpload.Enabled = true;
        }
    }
}
